package com.elitesland.b2c.com.repo;

import com.elitesland.b2c.com.entity.QComAreaDO;
import com.elitesland.core.constant.CommonConstant;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 功能说明
 * </p>
 *
 * @author fred
 * @since 2021-02-01 17:29:32
 */
@Repository
public class ComAreaRepoProc {

    @Autowired
    private JPAQueryFactory jpaQueryFactory;

    private final QComAreaDO qComAreaDO = QComAreaDO.comAreaDO;

    /**
     * 更新是否启用
     *
     * @param ids    区域ID
     * @param enable 是否启用
     */
    public void updateEnable(List<Long> ids, Boolean enable) {
        jpaQueryFactory.update(qComAreaDO)
                .set(qComAreaDO.enabled, enable)
                .where(qComAreaDO.id.in(ids))
                .execute();
    }

    /**
     * 删除区域信息
     *
     * @param ids 区域ID
     */
    public void delete(List<Long> ids) {
        jpaQueryFactory.update(qComAreaDO)
                .set(qComAreaDO.deleteFlag, CommonConstant.COMMON_DELETE_YES)
                .where(qComAreaDO.id.in(ids))
                .execute();
    }

    /**
     * 查询地区ID与名字的映射
     *
     * @return 查询地区ID与名字的映射
     */
    public Map<Long, String> queryNames() {
        return jpaQueryFactory.select(qComAreaDO.id, qComAreaDO.name)
                .from(qComAreaDO)
                .fetch()
                .stream()
                .collect(Collectors.toMap(t -> t.get(qComAreaDO.id), t -> t.get(qComAreaDO.name), (t1, t2) -> t1));
    }

    public Map<Long, String> queryNames(List<Long> ids) {
        return jpaQueryFactory.select(qComAreaDO.id, qComAreaDO.name)
                .from(qComAreaDO)
                .where(qComAreaDO.id.in(ids))
                .fetch()
                .stream()
                .collect(Collectors.toMap(t -> t.get(qComAreaDO.id), t -> t.get(qComAreaDO.name), (t1, t2) -> t1));
    }

    /**
     * 查询子节点数量
     *
     * @param ids 区域ID
     * @return 区域ID与子节点的数量映射
     */
    public Map<Long, Long> queryChildrenNum(List<Long> ids) {
        return jpaQueryFactory.select(qComAreaDO.id, qComAreaDO.parentId)
                .from(qComAreaDO)
                .where(qComAreaDO.parentId.in(ids))
                .fetch()
                .stream()
                .collect(Collectors.groupingBy(t -> t.get(qComAreaDO.parentId), Collectors.counting()));
    }

    /**
     * 查询分类
     *
     * @param id 区域ID
     * @return 区域分类
     */
    public String getCategory(Long id) {
        return jpaQueryFactory.select(qComAreaDO.category)
                .from(qComAreaDO)
                .where(qComAreaDO.id.eq(id))
                .fetchOne();
    }

    /**
     * 获取名称
     *
     * @param id 区域ID
     * @return 区域名称
     */
    public String getName(Long id) {
        return jpaQueryFactory.select(qComAreaDO.name)
                .from(qComAreaDO)
                .where(qComAreaDO.id.eq(id))
                .fetchOne();
    }

    /**
     * 获取启用状态
     *
     * @param id 区域ID
     * @return 是否启用
     */
    public Boolean getEnable(Long id) {
        return jpaQueryFactory.select(qComAreaDO.enabled)
                .from(qComAreaDO)
                .where(qComAreaDO.id.eq(id))
                .fetchOne();
    }

    /**
     * 判断区域名称是否存在
     * <p>
     * 同一级下名称不能相同
     *
     * @param parentId 上级ID
     * @param name     区域名称
     * @param id       区域ID
     * @return 是否存在
     */
    public boolean existsName(@NonNull Long parentId, @NonNull String name, Long id) {
        Predicate predicate = qComAreaDO.parentId.eq(parentId)
                .and(qComAreaDO.name.eq(name))
                .and(qComAreaDO.deleteFlag.eq(CommonConstant.COMMON_DELETE_NO));
        if (id != null) {
            predicate = ExpressionUtils.and(predicate, qComAreaDO.id.ne(id));
        }

        return jpaQueryFactory.select(qComAreaDO.id)
                .from(qComAreaDO)
                .where(predicate)
                .limit(1)
                .fetchOne() != null
                ;
    }

}